import { Context, Next } from 'koa';

/**
 * CORS配置接口
 */
export interface CorsOptions {
  origin?: string | string[] | ((ctx: Context) => string | Promise<string>);
  allowMethods?: string | string[];
  allowHeaders?: string | string[];
  exposeHeaders?: string | string[];
  credentials?: boolean;
  maxAge?: number;
  optionsSuccessStatus?: number;
}

/**
 * 默认CORS配置
 */
const defaultOptions: CorsOptions = {
  origin: '*',
  allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'PATCH', 'HEAD'],
  allowHeaders: [
    'Content-Type',
    'Authorization',
    'Accept',
    'Origin',
    'User-Agent',
    'DNT',
    'Cache-Control',
    'X-Mx-ReqToken',
    'Keep-Alive',
    'X-Requested-With',
    'If-Modified-Since',
    'X-CSRF-Token'
  ],
  exposeHeaders: [],
  credentials: false,
  maxAge: 86400, // 24小时
  optionsSuccessStatus: 204
};

/**
 * 解析origin配置
 */
const resolveOrigin = async (origin: CorsOptions['origin'], ctx: Context): Promise<string> => {
  if (typeof origin === 'string') {
    return origin;
  }
  
  if (Array.isArray(origin)) {
    const requestOrigin = ctx.get('Origin');
    if (origin.includes(requestOrigin)) {
      return requestOrigin;
    }
    return origin[0] || '*';
  }
  
  if (typeof origin === 'function') {
    return await origin(ctx);
  }
  
  return '*';
};

/**
 * 格式化头部值
 */
const formatHeaders = (headers: string | string[]): string => {
  if (Array.isArray(headers)) {
    return headers.join(', ');
  }
  return headers;
};

/**
 * CORS中间件
 */
export const cors = (options: CorsOptions = {}) => {
  const opts = { ...defaultOptions, ...options };
  
  return async (ctx: Context, next: Next) => {
    // 解析origin
    const origin = await resolveOrigin(opts.origin, ctx);
    
    // 设置CORS头部
    if (origin !== 'false') {
      ctx.set('Access-Control-Allow-Origin', origin);
    }
    
    // 设置允许的方法
    if (opts.allowMethods) {
      ctx.set('Access-Control-Allow-Methods', formatHeaders(opts.allowMethods));
    }
    
    // 设置允许的头部
    if (opts.allowHeaders) {
      ctx.set('Access-Control-Allow-Headers', formatHeaders(opts.allowHeaders));
    }
    
    // 设置暴露的头部
    if (opts.exposeHeaders && opts.exposeHeaders.length > 0) {
      ctx.set('Access-Control-Expose-Headers', formatHeaders(opts.exposeHeaders));
    }
    
    // 设置是否允许携带凭证
    if (opts.credentials === true) {
      ctx.set('Access-Control-Allow-Credentials', 'true');
    }
    
    // 设置预检请求缓存时间
    if (opts.maxAge) {
      ctx.set('Access-Control-Max-Age', String(opts.maxAge));
    }
    
    // 处理OPTIONS预检请求
    if (ctx.method === 'OPTIONS') {
      ctx.status = opts.optionsSuccessStatus || 204;
      ctx.body = '';
      return;
    }
    
    await next();
  };
};

/**
 * 创建开发环境CORS配置
 */
export const createDevCors = (allowedOrigins: string[] = ['http://localhost:3000', 'http://127.0.0.1:3000']) => {
  return cors({
    origin: (ctx: Context) => {
      const requestOrigin = ctx.get('Origin');
      if (allowedOrigins.includes(requestOrigin)) {
        return requestOrigin;
      }
      return allowedOrigins[0];
    },
    credentials: true,
    allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'PATCH'],
    allowHeaders: [
      'Content-Type',
      'Authorization',
      'Accept',
      'Origin',
      'User-Agent',
      'X-Requested-With',
      'X-CSRF-Token'
    ]
  });
};

/**
 * 创建生产环境CORS配置
 */
export const createProdCors = (allowedOrigins: string[]) => {
  return cors({
    origin: allowedOrigins,
    credentials: true,
    allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
    allowHeaders: [
      'Content-Type',
      'Authorization',
      'Accept',
      'Origin',
      'X-Requested-With'
    ],
    maxAge: 86400 // 24小时缓存
  });
};